/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Windows Forms Controls Class Library
 * Version 2.00
 * 
 * Dialog Header Class
 *      Provides an MSI-style form header for modal dialog forms.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using System.Text;
using System.ComponentModel;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace Adaptive.Foundation.Windows.Forms
{
    /// <summary>
    /// Provides an MSI-style form header for modal dialog forms.
    /// </summary>
    [Browsable(true), ToolboxItem(true)]
    public partial class DialogHeader : AdaptiveControlBase
    {
        /*--------------------------------------------------------------------------------
         * Public Event Definitions
         *------------------------------------------------------------------------------*/
        #region Public Event Definitions
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Constants Declarations
         *------------------------------------------------------------------------------*/
        #region Private Constants Declarations
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Member Declarations
         *------------------------------------------------------------------------------*/
        #region Private Member Declarations
		private Bitmap[] _shadows;
		private Image _image;
		private Image _resizeImage;
		private string _title = string.Empty;
		private string _text = string.Empty;
        #endregion

        /*--------------------------------------------------------------------------------
         * Constructor / Dispose / Destructor Methods
         *------------------------------------------------------------------------------*/
        #region Constructor / Dispose / Destructor Methods
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <remarks>
        /// This is the default constructor.
        /// </remarks>
        public DialogHeader()
            : base()
        {
            InitializeComponent();
			SetStyle(ControlStyles.ResizeRedraw, true);
			TabStop = false;
        }
        /// <summary>
        /// Deallocates internally allocated objects.
        /// </summary>
        /// <param name="disposing">
        /// A value indicating whether the object is being disposed.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                    components.Dispose();
                if (_image != null)
                    _image.Dispose();

                if (_shadows != null)
                {
                    try
                    {
                        for (int count = 2; count >= 0; count--)
                        {
                            if (_shadows[count] != null)
                                _shadows[count].Dispose();

                            Array.Clear(_shadows, 0, 3);
                        }
                    }
                    catch
                    { }
                }
            }

            _shadows = null;
            _image = null;
            _text = null;
            _title = null;

            components = null;
            base.Dispose(disposing);
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Properties
         *------------------------------------------------------------------------------*/
        #region Public Properties
        /// <summary>
        /// Gets or sets the title to be displayed.
        /// </summary>
        /// <value>
        /// Caption title text.
        /// </value>
        [Browsable(true),
        DefaultValue("MyTitle"),
        Description("Gets or sets the bolded caption text for the control.")]
        public string Caption
        {
            get
            {
                return _title;
            }
            set
            {
                _title = value;
                Invalidate();
            }
        }
        /// <summary>
        /// Gets or sets the image to be displayed.
        /// </summary>
        /// <value>
        /// An <see cref="Image"/> instance or <b>null</b> for no image.
        /// </value>
        [Browsable(true),
        Description("Gets or sets the image to be displayed on the control.")]
        public Image Image
        {
            get
            {
                return _image;
            }
            set
            {
                _image = value;
                if (_image != null)
                {
                    _resizeImage = GetResizeImage(_image);
                    if (_shadows == null)
                        _shadows = new Bitmap[3];
                    _shadows[0] = GetShadowImage(Color.FromArgb(40, 187, 187, 187));
                    _shadows[1] = GetShadowImage(Color.FromArgb(80, 167, 167, 167));
                    _shadows[2] = GetShadowImage(Color.FromArgb(86, 147, 147, 147));
                }
                Invalidate();
            }
        }
        /// <summary>
        /// Gets or sets the instructions text to be displayed.
        /// </summary>
        /// <value>
        /// Caption instructions text text.
        /// </value>		
        [Browsable(true),
        Description("Gets or sets the descriptive text to be displayed on the control.")]
        public string InstructionText
        {
            get
            {
                return _text;
            }
            set
            {
                base.Text = value;
                _text = value;
                Invalidate();
            }
        }
        /// <summary>
        /// Gets a value indicating whether the control is a tab-stop control.
        /// </summary>
        /// <value>
        /// Always <b>false</b>.
        /// </value>
        [Browsable(false)]
        public new bool TabStop
        {
            get { return false; }
            set
            {
                base.TabStop = false;
            }
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Protected Methods / Event Methods
         *------------------------------------------------------------------------------*/
        #region Protected Methods / Event Methods
        /// <summary>
        /// Paints the background of the control.
        /// </summary>
        /// <param name="e">
        /// A <see cref="PaintEventArgs"/> event arguments object containing the 
        /// <see cref="Graphics"/> object used to draw the control.
        /// </param>
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            LinearGradientBrush brush = null;
            Rectangle rect;
            Color grayColor;

            //Raise the base event.
            base.OnPaintBackground(e);

            //Paint the basic background.
            e.Graphics.FillRectangle(Brushes.White, 0, 0, Width, Height);

            //Create objects to fill in the right-side fade.
            grayColor = Color.FromArgb(40, 187, 187, 187);
            rect = new Rectangle(Width - 41, 0, 42, Height);
            brush = new LinearGradientBrush(rect, Color.White, grayColor,
                LinearGradientMode.Horizontal);

            //Fill in overlay.
            e.Graphics.FillRectangle(brush, rect);

            //Clear memory.
            brush.Dispose();
            brush = null;

            //Draw bottom two divider lines.
            e.Graphics.DrawLine(SystemPens.ControlDark, 0, Height - 2, Width, Height - 2);
            e.Graphics.DrawLine(SystemPens.ControlLight, 0, Height - 1, Width, Height - 1);
        }
        /// <summary>
        /// Paints the control content.
        /// </summary>
        /// <param name="e">
        /// A <see cref="PaintEventArgs"/> event arguments object containing the 
        /// <see cref="Graphics"/> object used to draw the control.
        /// </param>
        protected override void OnPaint(PaintEventArgs e)
        {
            //Render image if present.
            if (_image != null)
            {
                DrawShadowImages(e.Graphics);
                DrawImage(e.Graphics);
            }
            DrawTitleText(e.Graphics);
            DrawRemainingText(e.Graphics);
        }
        /// <summary>
        /// Raises the <see cref="Control.Resize"/> event and re-sets the underlying image
        /// objects.
        /// </summary>
        /// <param name="e">A <see cref="System.EventArgs"/> event arguments 
        /// object.</param>
        protected override void OnResize(EventArgs e)
        {
            //Call base method.
            base.OnResize(e);

            //Reset image.
            Image = _image;
        }
        /// <summary>
        /// This method is invoked in the main UI thread to perform any neccessary
        /// updates to the UI.
        /// </summary>
        /// <remarks>
        /// Calling the related <see cref="AdaptiveControlBase.UpdateControl()"/> is used to prevent illegal 
        /// cross-threaded UI update calls.
        /// </remarks>
        protected override void UpdateCurrentControlContents()
        {
            Invalidate();
            Refresh();
        }
        /// <summary>
        /// This method is invoked in the main UI thread to perform any neccessary
        /// updates to the UI.
        /// </summary>
        /// <remarks>
        /// Calling the related <see cref="AdaptiveControlBase.UpdateControl(object[])"/> is used to prevent illegal 
        /// cross-threaded UI update calls.
        /// </remarks>
        /// <param name="data">
        /// The data supplied to the control to update the internal controls with.
        /// </param>
        protected override void UpdateCurrentControlContents(object[] data)
        {
            Invalidate();
            Refresh();
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Methods / Functions
         *------------------------------------------------------------------------------*/
        #region Public Methods / Functions
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Event Handlers
         *------------------------------------------------------------------------------*/
        #region Private Event Handlers
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Methods / Functions
         *------------------------------------------------------------------------------*/
        #region Private Methods / Functions
        /// <summary>
        /// Draws the shadows under the image.
        /// </summary>
        /// <param name="g">The <see cref="Graphics"/> instance used to perform drawing tasks.</param>
        private void DrawShadowImages(Graphics g)
        {
            Point imagePoint = GetImagePoint();
            if (_shadows != null)
            {
                if (_shadows[0] != null)
                    g.DrawImage(_shadows[0], new Point(imagePoint.X + 3, imagePoint.Y+3));

                if (_shadows[1] != null)
                    g.DrawImage(_shadows[1], new Point(imagePoint.X + 2, imagePoint.Y+2));

                if (_shadows[2] != null)
                    g.DrawImage(_shadows[2], new Point(imagePoint.X + 1, imagePoint.Y+1));
            }
        }
        private void DrawImage(Graphics g)
        {
            Point imagePoint = GetImagePoint();
            if (_image != null)
            {
                if (Height < 40)
                    g.DrawImage(_image, new Rectangle(imagePoint.X, imagePoint.Y, 16, 16));
                else if (Height < 80)
                    g.DrawImage(_image, new Rectangle(imagePoint.X, imagePoint.Y, 32, 32));
                else
                    g.DrawImage(_image, new Point(imagePoint.X, imagePoint.Y));
            }

        }
        private Bitmap GetResizeImage(Image image)
        {
            Bitmap returnValue = null;
            Graphics g = null;

            if (Height < 40)
            {
                returnValue = new Bitmap(16, 16);
                g = Graphics.FromImage(returnValue);
                g.DrawImage(_image, new Rectangle(0, 0, 16, 16));
                g.Dispose();
            }
            else if (Height < 80)
            {
                returnValue = new Bitmap(32, 32);
                g = Graphics.FromImage(returnValue);
                g.DrawImage(_image, new Rectangle(0, 0, 32, 32));
                g.Dispose();
            }
            else
            {
                returnValue = new Bitmap(image.Width, image.Height);
                g = Graphics.FromImage(returnValue);
                g.DrawImage(_image, new Rectangle(0, 0, image.Width, image.Height));
                g.Dispose();
            }
            g = null;
            return returnValue;

        }
        private Bitmap GetShadowImage(Color shadowColor)
        {
            Bitmap returnValue = null;			//Return value.
            int x = 0;
            int y = 0;
            int xMax = 0;
            int yMax = 0;

            returnValue = new Bitmap(_resizeImage);
            xMax = returnValue.Width;
            yMax = returnValue.Height;

            for (x = 0; x < xMax; x++)
            {
                for (y = 0; y < yMax; y++)
                {
                    if (returnValue.GetPixel(x, y).A == 255)
                        returnValue.SetPixel(x, y, shadowColor);
                }
            }

            return returnValue;
        }
        private void DrawTitleText(Graphics g)
        {
            Font font = null;
            SolidBrush brush = null;

            brush = new SolidBrush(Color.FromArgb(40, 187, 187, 187));
            font = new Font(base.Font, FontStyle.Bold);
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
            g.DrawString(_title, font, brush,12, 6);
            brush.Dispose();

            brush = new SolidBrush(Color.FromArgb(80, 187, 187, 187));
            g.DrawString(_title, font, brush, 12, 5);
            brush.Dispose();

            g.DrawString(_title, font, Brushes.Black, 12, 4);

            font.Dispose();
            font = null;
            brush = null;
        }
        private void DrawRemainingText(Graphics g)
        {
            g.DrawString(_text, Font, Brushes.Black, new RectangleF(20, 24, Width - 42,
                Height - 20));
        }

        private Point GetImagePoint()
        {
            Point returnValue = new Point();

            returnValue.Y=4;
            if (Height < 40)
                returnValue.X = Width - 20;
            else if (Height < 80)
                returnValue.X = Width - 36;
            else
                returnValue.X = Width - (_image.Width + 4);

            return returnValue;
        }
        #endregion

    }
}
